import { MainAxisSize, Spacer } from './../../layout/Flex';
import { Alignment } from "@/framework/layout/Container";
import Stack from "@/framework/layout/Stack";
import CanvasComponent, { CanvasComponentOptions } from "./CanvasComponent";
import Text, { TextAlign } from "./Text";
import { ComponentInterface } from "@/framework/core/Component";
import Row from "@/framework/layout/Row";
import { Tween, Group, Easing } from '@tweenjs/tween.js';
import RectFill from './RectFill';

export class SegmentIndicator extends CanvasComponent {
  color: string
  segment: Segment
  constructor(options: {
    color: string
  }) {
    super({
      ...options,
      x: 0,
      y: 0
    })
    this.color = options.color
  }
  async draw(context: CanvasRenderingContext2D, dt: number): Promise<void> {
    if(typeof this.screenX === 'number' && typeof this.screenY === 'number') {
      context.save()
      if(this.segment.borderRadius !== null && this.segment.borderRadius !== undefined) {
        context.beginPath();
        context.roundRect(this.segment.screenX, this.segment.screenY, this.segment.width, this.segment.height, this.segment.borderRadius)
        context.clip();
      }
      context.fillStyle = `${this.color}`
      context.fillRect(this.screenX, this.screenY, this.width, this.height)
      context.restore()
    }
  }
}

export type SegmentOptions = CanvasComponentOptions & {
  contents: string[]
  alignment?: Alignment
  activeIndex?: number
  indicatorColor?: string
  color?: string
  activeColor?: string,
  lineHeight?: number
  fontSize?: number
}

export default class Segment extends Stack {
  contents: string[]
  indicator: SegmentIndicator
  row: Row
  items: Spacer[]
  activeIndex: number
  color: string
  activeColor: string
  tweenGroup: Group
  borderRadius?: number | number[]
  declare options: SegmentOptions

  constructor(options: CanvasComponentOptions & {
    contents: string[]
    alignment?: Alignment
    activeIndex?: number
    indicatorColor?: string
    color?: string
    activeColor?: string,
    lineHeight?: number
    fontSize?: number
    borderRadius?: number | number[]
  }) {
    var background = new RectFill({
      borderRadius: options.borderRadius ?? 10,
      borderColor: options.indicatorColor,
      borderWidth: 1,
      width: options.width,
      height: options.height
    })
    var indicator = new SegmentIndicator({
      color: options.indicatorColor
    })
    var items = options.contents.map((text, index) => {
      return new Spacer({ 
        child: new Text(text, {
          color: options.color,
          lineHeight: options.lineHeight ?? 38,
          fontSize: options.fontSize ?? 12,
          clickable: true,
          textAlign: TextAlign.center,
          onClick: () => this.onTextClick.call(this, index)
        })
      })
    })
    var row = new Row({
      children: items,
      width: options.width,
      mainAxisSize: MainAxisSize.max
    })
    super({
      ...options,
      alignment: Alignment.topCenter,
      children: [
        background,
        indicator,
        row
      ] as ComponentInterface[]
    })
    this.indicator = indicator
    this.row = row
    this.items = items
    this.activeIndex = options.activeIndex
    this.tweenGroup = new Group()
    this.color = options.color
    this.activeColor = options.activeColor
    this.borderRadius = options.borderRadius ?? 4

    indicator.segment = this
  }

  async init(): Promise<void> {
    super.init()
    this.resize()
  }

  async resize(): Promise<void> {
    await super.resize()
    if(typeof this.activeIndex != 'number') {
      this.activeIndex = 0
    }
    if(typeof this.width != 'number') {
      var sumWidth = this.items.reduce((preV, curV)=> preV + curV.width, 0)
      this.width = sumWidth
    }
    if(typeof this.height != 'number') {
      var height = this.indicator.height
      this.height = height
    }
    this.indicator.screenY = this.screenY
    this.indicator.height = this.height
  }

  async update(dt: number): Promise<void> {
      super.update(dt)
      if(!this.tweenGroup || this.tweenGroup.allStopped()) {
        if(this.items.length > this.activeIndex) {
          this.indicator.screenX = this.items[this.activeIndex].screenX
          this.indicator.width = this.items[this.activeIndex].width
        }
      } else {
        this.tweenGroup.update(dt)
      }
  }

  async destroy(): Promise<void> {
      this.tweenGroup.removeAll()
      this.tweenGroup = null
  }

  onTextClick(index: number) {
    var lastIndex = this.activeIndex
    var currentIndex = index

    var lastItem = this.items[lastIndex]
    var currentItem = this.items[currentIndex]

    this.activeIndex = index
    this.tweenGroup.removeAll()
    const progress = {value: 0}
    var tween = new Tween(progress)
    .to({
      value: 1
    }, 250)
    .easing(Easing.Quadratic.InOut) 
		.onUpdate(() => {
      this.indicator.screenX = this.getProgressValue(currentItem.screenX, lastItem.screenX, progress.value)
      this.indicator.width = this.getProgressValue(currentItem.width, lastItem.width, progress.value)
    })
    .onComplete(() => {
      console.log('onComplete')
    })
    .start()
    this.tweenGroup.add(tween)
    
    var curText = currentItem.child as Text
    var lastText = lastItem.child as Text
    curText.color = this.activeColor
    lastText.color = this.color
  }

  getProgressValue(curV: number, lastV: number, processValue: number) {
    return lastV + (curV - lastV) * processValue
  }
}